package com.wang.security.filter;

import com.alibaba.fastjson2.JSON;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.wang.common.result.ResponseUtil;
import com.wang.common.result.Result;
import com.wang.common.utils.JwtHelper;
import com.wang.model.system.SysLoginLog;
import com.wang.model.system.vo.LoginVo;
import com.wang.security.custom.CustomUser;
import org.jetbrains.annotations.NotNull;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;

import javax.annotation.Resource;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * @author wjh
 * @create 2023-05-27
 */
public class TokenLoginFilter extends UsernamePasswordAuthenticationFilter {

    private StringRedisTemplate stringRedisTemplate;



    //构造方法
    public TokenLoginFilter(AuthenticationManager authenticationManager,StringRedisTemplate stringRedisTemplate) {
        this.setAuthenticationManager(authenticationManager);
        this.setPostOnly(false);
        //指定登录接口及提交方式，可以指定任意路径
        this.setRequiresAuthenticationRequestMatcher(new AntPathRequestMatcher("/admin/system/index/login", "POST"));
        this.stringRedisTemplate = stringRedisTemplate;
    }

    //登录认证过程
    //获取登录的用户名和密码，调用方法认证
    public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {
        try {
            //获取输入的用户的信息
            //TODO
            LoginVo loginVo = new ObjectMapper().readValue(request.getInputStream(), LoginVo.class);
            //封装对象
            //TODO
            Authentication authentication = new UsernamePasswordAuthenticationToken(loginVo.getUsername(), loginVo.getPassword());
            //调用方法
            //TODO
            return this.getAuthenticationManager().authenticate(authentication);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    //认证成功
    protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain, @NotNull Authentication authResult) throws IOException, ServletException {
        //获取当前认证用户的对象
        CustomUser customUser = (CustomUser) authResult.getPrincipal();
        String username = customUser.getUsername();
        //生成token
        String token = JwtHelper.createToken(customUser.getSysUser().getId(), customUser.getSysUser().getUsername());
        //保存用户的权限集合到redis
        stringRedisTemplate.opsForValue().set("perms:"+customUser.getUsername(), JSON.toJSONString(customUser.getAuthorities()));
        stringRedisTemplate.opsForValue().increment("PV:"+LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd")),1);
        //返回
        Map<String,Object> map = new HashMap<>();
        map.put("token",token);
        ResponseUtil.out(response, Result.success(map));
    }



    //认证失败
    protected void unsuccessfulAuthentication(HttpServletRequest request, HttpServletResponse response, AuthenticationException failed) throws IOException, ServletException {
        ResponseUtil.out(response,Result.error("认证失败"));
    }
}